<script setup lang="ts">
import './styles'

import { useFullscreen } from '@vueuse/core'
import type { Ref } from 'vue'

import type {
  CascaderNodeModel,
  CdnCascaderProps
} from '@/components/Cascader/types'

import type { CascaderDiff, CascaderUpdateModel } from '.'
import LevelCard from './components/LevelCard.vue'
import { NodeEmptyTipsProvideKey } from './config'
import { defaultEmptyTips } from './constants/defaultValue'
import { useBuildData } from './hooks/useBuildData'
import { useCascaderStore } from './hooks/useCascaderStore'
import { useWatchElement } from './hooks/useWatchElement'

type IEmits = {
  (event: 'node-click', isChanged: boolean, node: CascaderNodeModel): void
}
const emit = defineEmits<IEmits>()
const props = withDefaults(defineProps<CdnCascaderProps>(), {
  data: () => ({ charts: [] })
})
const modelValue = ref<CascaderUpdateModel>()
const diffValue = defineModel<CascaderDiff[]>('diff')
const tipsValue = inject('tipsValue') as Ref<{
  error: number
  warning: number
  risks: string[]
}>

const { dataSource, doLayout } = useBuildData(toRef(props, 'data'))

const emptyTips = computed(() =>
  Object.assign({}, defaultEmptyTips, props?.nodeEmptyTips || {})
)

const { diff } = useCascaderStore()
const cdnCascaderEl = ref<HTMLElement>()

useWatchElement({
  el: cdnCascaderEl,
  className: 'node-sortable-ghost',
  specifiedClass: 'is-sortable'
})

provide(NodeEmptyTipsProvideKey, emptyTips)

const updateModelValue = () => {
  const data = dataSource.value!.charts!
  modelValue.value = data
}

const updateTipsValue = () => {
  tipsValue.value = dataSource.value!.charts.reduce(
    (acc, item) => {
      if (!item?.node_L1?.length) {
        acc.error += 1
        acc.risks.push(`【${item.region_name}】 缺少 L1层级，请求将无法解析`)
      } else if (!item?.node_L2?.length) {
        acc.warning += 1
        acc.risks.push(
          `【${item.region_name}】 缺少 L2 层级节点，L1 层级节点直接向源站回源`
        )
      }
      return acc
    },
    { warning: 0, error: 0, risks: [] as string[] }
  )!
}

watchPostEffect(() => {
  diffValue.value = diff.value
  updateModelValue()
  updateTipsValue()
})

const { enter, exit, toggle } = useFullscreen(cdnCascaderEl)

const position = (type?: 'error' | 'warning') => {
  const el = cdnCascaderEl.value?.querySelector(
    type ? `.cascader-level-card--${type}` : '.cascader-level-card--tips'
  )
  el?.scrollIntoView?.({
    behavior: 'smooth'
  })
}
const isConfirm = computed(() => {
  const isDiff = diff.value.some((obj) =>
    ['LEVEL', 'REGION', 'REGION_LEVEL'].includes(obj.diffType)
  )

  const tipsDiff = tipsValue.value?.risks && tipsValue.value.risks.length > 0

  return isDiff || tipsDiff
})

const disabled = computed(() => diff.value.length == 0)

defineExpose({
  // isFullscreen,
  enter,
  exit,
  toggle,
  position,
  modelValue,
  isConfirm,
  disabled,
  doLayout
})

const scrollRef = ref()
const wrapWidth = ref(0)
provide('cascadeWrapWidth', wrapWidth)
function calcWrapWidth() {
  if (!scrollRef.value) {
    return
  }
  wrapWidth.value = scrollRef.value!.wrapRef.offsetWidth
}
window.onresize = calcWrapWidth
onMounted(calcWrapWidth)
</script>

<template>
  <div ref="cdnCascaderEl" class="cdn-cascader">
    <slot name="exit-fullscreen"></slot>
    <div class="cdn-cascader__content">
      <cloud-scrollbar
        ref="scrollRef"
        :wrap-class="[
          'cdn-cascader__content--scrollbar',
          isFullscreen ? 'is-fullscreen' : ''
        ]">
        <level-card
          v-for="region in dataSource?.charts || []"
          :key="region.region_id"
          v-show="dataSource?.charts?.length"
          :region="region"
          @node-click="(node) => emit('node-click', diff.length > 0, node)" />
        <div
          v-show="!dataSource?.charts?.length"
          class="flex-col flex-center gap-y-2 w-full !h-full flex-1 min-h-600px bg-white">
          <img
            src="@/assets/images/node-cascade-empty.png"
            width="80"
            height="80"
            alt="" />
          <span class="text-3 text-sm/22px"
            >节点暂未安装，请前往
            <span
              class="text-primary cursor-pointer"
              @click="$router.push({ name: 'NodeList' })"
              >节点列表</span
            >
            安装节点</span
          >
        </div>
      </cloud-scrollbar>
    </div>
  </div>
</template>
